package net.qiyuesuo.thread;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Date;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import net.qiyuesuo.pojo.FileMeta;
import net.qiyuesuo.utils.RandomUtils;

/**
 * 通过多线程创建临时文件，写数据
 * @author Administrator
 *
 */
public class WriteInfoByTempFiles {
	
	public static void main(String[] args) throws InterruptedException {
		//使用线程数
		int threadNum = 5;
		//存储文件数
		int fileNum = 5000;
		ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
		CountDownLatch count = new CountDownLatch(threadNum);
		//将需要存储的元数据放入队列
		for(int i=0;i<fileNum ;i++) {
			//模拟存储
			FileMeta info = new FileMeta(RandomUtils.getRandomFileKey(),333L,new Date());
			queue.offer("文件："+i+info.toJson());
		}
		//开始执行
		long start = System.currentTimeMillis();
		//执行5个线程，从队列中取出元素,存在临时文件中
		ExecutorService service = Executors.newFixedThreadPool(threadNum+1);
		for(int i =0;i<threadNum;i++) {
			service.submit(new SaveInfoToTempFileTask(queue, "_线程"+i, count));
		}
		//监听 所有完成后 存入metaData.txt
		count.await();
		CountDownLatch waitFinish = new CountDownLatch(1);
		service.submit(new SaveInfoToTureFileTask(queue, threadNum,waitFinish));
		//在存储完临时数据之后集合数据
		waitFinish.await();
		service.shutdown();
		long time = System.currentTimeMillis() - start;
		Logger logger = LoggerFactory.getLogger(WriteInfoByTempFiles.class);
		logger.info("-------------------耗时----------------------");
		logger.info("时间为："+time +"ms");
	}
	
	
	
	private static class SaveInfoToTempFileTask  implements Runnable{
		private ConcurrentLinkedQueue<String> queue;
		private String name;
		private CountDownLatch count;
		private Logger logger = LoggerFactory.getLogger(getClass());
		
		public SaveInfoToTempFileTask(ConcurrentLinkedQueue<String> queue,String name,CountDownLatch count) {
			
			this.queue = queue;
			this.name = name ;
			this.count = count;
		}

		@Override
		public void run() {
			Path path = Paths.get("C:\\Users\\Administrator\\Desktop\\File\\Logs\\metadata"+name+".txt");
			while(!queue.isEmpty()) {
				//队列不为空  从队列中取出一个元素，存储一条数据
				if(!Files.exists(path, LinkOption.NOFOLLOW_LINKS)) {
					try {
						Files.createFile(path);
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
				String meta = queue.poll();
				if(meta != null) {
					try {
						Files.write(path, (meta+"\r\n").getBytes(), StandardOpenOption.APPEND);
						logger.info("【文件："+meta+"】"+",被线程:"+name);
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
			count.countDown();//计数器 -1
		}
		}
		
	private static class SaveInfoToTureFileTask implements Runnable{
		
		private ConcurrentLinkedQueue queue;
		private int threadNum;
		private CountDownLatch count;
		
		public SaveInfoToTureFileTask(ConcurrentLinkedQueue queue,int threadNum,CountDownLatch count) {
			this.queue = queue;
			this.threadNum = threadNum;
			this.count = count;
		}

		@Override
		public void run() {
				boolean hasSave = true;
				if (queue.isEmpty() && hasSave) {
					// 当队列为空（所有数据存入临时文件）
					for (int i = 0; i < threadNum; i++) {
							try {
								byte[] bytes = Files.readAllBytes(Paths.get("C:\\Users\\Administrator\\Desktop\\File\\Logs\\metadata" + "_线程" + i + ".txt"));
								String result = new String(bytes);
								Files.write(Paths.get("C:\\Users\\Administrator\\Desktop\\File\\Logs\\metadata.txt"), result.getBytes(), StandardOpenOption.APPEND);
							} catch (IOException e) {
								e.printStackTrace();
							}
					}
					hasSave = false;
					count.countDown();
				}
		}

		
	}
		
	
	
}
